﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ChronoScript_Compiler.Language
{
    public class LanguageDefinition
    {
        public class SyntaxNode { }

        public class ChronObject : SyntaxNode { 
            public List<Field> fields;
            public List<Method> methods;
        }

        public class ChronoClass : SyntaxNode
        {
            public string name;
            public string extends = "";
            public List<Declaration> Field = new List<Declaration>();
            public List<Method> Functions = new List<Method>();
        }

        public class CodeBlock : SyntaxNode
        {
            public List<SyntaxNode> body = new List<SyntaxNode>();
        }

        public class Field : Declaration
        {
            public bool Public;
            public bool Static;

            public Field(bool Public, bool Static, string name, string type, Expression value)
                : base(name, type, value)
            {
                this.Public = Public;
                this.Static = Static;
                this.Name = name;
                this.Type = type;
                this.Value = value;
            }

            public Field(bool Public, bool Static, string name, string type)
                : base(name, type)
            {
                this.Public = Public;
                this.Static = Static;
                this.Name = name;
                this.Type = type;
            }
        }

        public class Declaration : SyntaxNode
        {
            public string Name;
            public string Type;
            public Expression Value = new Expression();
            public Declaration(string name, string type, Expression value)
            {
                this.Name = name;
                this.Type = type;
                this.Value = value;
            }

            public Declaration(string name, string type)
            {
                this.Name = name;
                this.Type = type;
            }
        }

        public class Method : SyntaxNode
        {
            public string name;
            public List<Declaration> arguments = new List<Declaration>();
            public string type;
            public CodeBlock body;
        }

        public class Expression : SyntaxNode
        {
            public List<SyntaxNode> Items = new List<SyntaxNode>();
        }

        public class Operator : SyntaxNode
        {
            public string theOperator;
            public SyntaxNode Op1, Op2;
        }

        public class StringLiteral : SyntaxNode
        {
            public string value;
            public StringLiteral(string value)
            {
                this.value = value;
            }
        }

        public class IntLiteral : SyntaxNode
        {
            public uint value;
            public IntLiteral(uint value)
            {
                this.value = value;
            }
        }

        public class Assignment : SyntaxNode
        {
            public string Name;
            public Expression Value = new Expression();
        }

        public class FunctionCall : SyntaxNode
        {
            public string Target;
            public List<Expression> Arguments = new List<Expression>();
        }

        public class IfStatement : SyntaxNode
        {
            public CodeBlock Body;
            public CodeBlock Else = new CodeBlock();
            public Expression Comparison;
        }

        public class WhileStatement : SyntaxNode
        {
            public CodeBlock Body;
            public Expression Comparison;
        }

        public class InlineIL : SyntaxNode
        {
            public string IL_Code = "";
        }

        public class SymbolRef : SyntaxNode
        {
            public string Value;
            public SymbolRef(string val)
            {
                this.Value = val;
            }
        }

        public class Plus : Operator { public Plus() { this.theOperator = "+"; } }
        public class Equal : Operator { public Equal() { this.theOperator = "=="; } }
        public class NotEqual : Operator { public NotEqual() { this.theOperator = "!="; } }
        public class Multiply : Operator { public Multiply() { this.theOperator = "*"; } }
        public class GreaterThan : Operator { public GreaterThan() { this.theOperator = ">"; } }
        public class LessThan : Operator { public LessThan() { this.theOperator = "<"; } }
        public class Subtract : Operator { public Subtract() { this.theOperator = "-"; } }
        public class And : Operator { public And() { this.theOperator = "&&"; } }
        public class Divide : Operator { }
        public class LeftBitshift : Operator { }
        public class RightBitshift : Operator { public override string ToString() { return ">>"; } }
    }
}
